//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

/* camera driver in emulator.
 * Ver. 1.0 , By Leng Bo, 2005-3-2
 * Ver. 1.1 , By Leng Bo, 2005-8-30
 * Ver. 2.0,  Porting to Elastos2.0, 2005-10-21
 */

#include <winhack.h>
#include <elasys_server.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <camdrv.h>
#include <camplus.h>

ECode CCamera::Read(
    /* [in] */ Int64 u64Offset,
    /* [in] */ Int32 bytesToRead,
    /* [out] */ MemoryBuf * pBuffer,
    /* [out] */ IEvent * * ppCompletionEvent)
{
    return E_NOT_IMPLEMENTED;
}

ECode CCamera::Write(
    /* [in] */ Int64 u64Offset,
    /* [in] */ const MemoryBuf & buffer,
    /* [out] */ Int32 * pBytesWritten,
    /* [out] */ IEvent * * ppCompletionEvent)
{
    return E_NOT_IMPLEMENTED;
}

ECode CCamera::Control(
    /* [in] */ Handle32 nControlCode,
    /* [in] */ const MemoryBuf & inBuffer,
    /* [out] */ MemoryBuf * pOutBuffer,
    /* [out] */ IEvent * * ppCompletionEvent)
{
    ECode ec = NOERROR;
    Camera_Format *pFormat;

    switch (nControlCode) {
        case 0:
            // Initialize camera device
            ec = g_CameraDriver.CamDrv_Initialize();
            break;

        case 1:
            // Quit camera device
            g_CameraDriver.CamDrv_Quit();
            break;

        case 2:
            // Get photo information and data
            // If continue snap is set, maybe there are more than 1 photo
            if (pOutBuffer == NULL) {
                return E_INVALID_ARGUMENT;
            }
            if (pOutBuffer->GetCapacity() < (int)sizeof(Camera_Photo)) {
                ec = E_OUT_OF_MEMORY;
                break;
            }
            ec = g_CameraDriver.CamDrv_GetSnapFrames((Camera_Photo *)pOutBuffer->GetPayload());

            pOutBuffer->SetUsed(sizeof(Camera_Photo));
            break;

        case 3:
            // Begin preview
            if (inBuffer.GetCapacity() < (int)sizeof(RECT)) {
                ec = E_OUT_OF_MEMORY;
                break;
            }
            ec = g_CameraDriver.CamDrv_BeginPreview((RECT *)inBuffer.GetPayload());
            break;

        case 4:
            // Stop preview
            ec = g_CameraDriver.CamDrv_StopPreview();
            break;

        case 5:
            // Release the memory of frames, except the default preview buffer.
            g_CameraDriver.CamDrv_ReleaseFrames();
            break;

        case 6:
            // Set many formats for camera device, such as photo quality, brightness ...
            if (inBuffer.GetCapacity() < (int)sizeof(Camera_Format)) {
                ec = E_OUT_OF_MEMORY;
                break;
            }

            pFormat = (Camera_Format *)inBuffer.GetPayload();

            ec = g_CameraDriver.CamDrv_SetAppFormat(pFormat->nID,
                    pFormat->wParam, pFormat->lParam);
            break;

        case 7:
            // Get many formats for camera device, such as photo quality, brightness ...
            if (pOutBuffer == NULL) {
                return E_INVALID_ARGUMENT;
            }
            if (inBuffer.GetCapacity() < (int)sizeof(int) ||
                pOutBuffer->GetCapacity() < (int)sizeof(Camera_Format)) {
                ec = E_OUT_OF_MEMORY;
                break;
            }

            pFormat = (Camera_Format *)pOutBuffer->GetPayload();
            pFormat->nID = *(int *)inBuffer.GetPayload();

            ec = g_CameraDriver.CamDrv_GetAppFormat(pFormat->nID,
                    &pFormat->wParam, &pFormat->lParam);
            pOutBuffer->SetUsed(sizeof(Camera_Format));
            break;
        case 8:
            // Enter photo/video mode.
            // Default thhe driver enters photo mode.
            if (inBuffer.GetPayload() == NULL) {
                g_CameraDriver.CamDrv_SetCamMode(0);
            }
            else {
                g_CameraDriver.CamDrv_SetCamMode(*(int *)inBuffer.GetPayload());
            }
            break;

        case 9:{
            // Begin video record
            if (NULL == ppCompletionEvent) {
                ec = E_INVALID_ARGUMENT;
                break;
            }
            ec = g_CameraDriver.CamDrv_BeginVideoRecord(ppCompletionEvent);
            break;
        }

        case 10:
            // Stop video record
            ec = g_CameraDriver.CamDrv_StopVideoRecord();
            break;

        case 11:{
            // Get image frame information and data,
            Camera_ImageFrame *pFrame;
            if (pOutBuffer == NULL) {
                return E_INVALID_ARGUMENT;
            }
            if (pOutBuffer->GetCapacity() < (int)sizeof(Camera_ImageFrame)) {
                ec = E_OUT_OF_MEMORY;
                break;
            }
            pFrame = (Camera_ImageFrame *)pOutBuffer->GetPayload();
            ec = g_CameraDriver.CamDrv_GetVideoFrame(pFrame);
            pOutBuffer->SetUsed(sizeof(Camera_ImageFrame));
            break;
        }

        // Power management code
        case 1000:
            break;

        case 1001:
        case 1002:
            break;

        default :
            ec = E_NOT_IMPLEMENTED;
            break;
    }

    return ec;
}

void CCamera::Dispose()
{
    delete this;
}

CCamera::CCamera()
{
}
